class window.Program
  constructor : (@ctx) ->
    @gl = @ctx.gl
    @vertexShader = @gl.createShader @gl.VERTEX_SHADER
    @fragmentShader = @gl.createShader @gl.FRAGMENT_SHADER
    @program = @gl.createProgram()
  
  setFragSource : (v) ->
    @gl.shaderSource @fragmentShader, v
    @gl.compileShader @fragmentShader

    if not @gl.getShaderParameter @fragmentShader, @gl.COMPILE_STATUS
      console.error "ERROR in fragmentshader: \n" + @gl.getShaderInfoLog @fragmentShader

    @gl.attachShader @program, @fragmentShader
  
  setVertSource : (v) ->
    @gl.shaderSource @vertexShader, v
    @gl.compileShader @vertexShader

    if not @gl.getShaderParameter @vertexShader, @gl.COMPILE_STATUS
      console.error "ERROR in vertexshader: \n" + @gl.getShaderInfoLog @vertexShader

    @gl.attachShader @program, @vertexShader

  u1f : (name, v) ->
    l = @gl.getUniformLocation @program, name
    @gl.uniform1f(l, v)

  u2f : (name, x, y) ->
    l = @gl.getUniformLocation @program, name
    @gl.uniform2f(l, x, y)

  u3f : (name, x, y, z) ->
    l = @gl.getUniformLocation @program, name
    @gl.uniform3f(l, x, y, z)

  u4f : (name, x, y, z, w) ->
    l = @gl.getUniformLocation @program, name
    @gl.uniform4f(l, x, y, z, w)

  u1i : (name, v) ->
    l = @gl.getUniformLocation @program, name
    @gl.uniform1i(l, v)

  u2i : (name, x, y) ->
    l = @gl.getUniformLocation @program, name
    @gl.uniform2i(l, x, y)

  u3i : (name, x, y, z) ->
    l = @gl.getUniformLocation @program, name
    @gl.uniform3i l, x, y, z

  u4i : (name, x, y, z, w) ->
    l = @gl.getUniformLocation @program, name
    @gl.uniform4i l, x, y, z, w

  um2f : (name, arr, t) ->
    t ?= false
    
    l = @gl.getUniformLocation @program, name

    @gl.uniformMatrix2fv l, t, arr

  um3f : (name, arr, t) ->
    t ?= false
    
    l = @gl.getUniformLocation @program, name

    @gl.uniformMatrix3fv l, t, arr

  um4f : (name, arr, t) ->
    t ?= false

    l = @gl.getUniformLocation @program, name
    @gl.uniformMatrix4fv l, t, arr

  attachTexture : (name, where, tex) ->
    me = @
    tex.loader.then () ->
      me.gl.activeTexture me.gl.TEXTURE0 + where
      tex.bind()
      me.u1i name, where



  link : ->
    @gl.linkProgram @program
    if not @gl.getProgramParameter @program, @gl.LINK_STATUS
      console.error "Error when linking program: \n #{@gl.getProgramInfoLog()}"

    @gl.validateProgram @program
    if not @gl.getProgramParameter @program, @gl.VALIDATE_STATUS
      console.error "Error when linking program: \n #{@gl.getProgramInfoLog()}"


  use : ->
    @gl.useProgram @program
    a = @ctx.screen()

    @u4f "screen", a.x, a.y, 1.0, 1.0
